﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using Emgu.CV.UI;
using Emgu.CV;
using System.Drawing;
using Emgu.CV.Structure;
using System.Threading;
using System.Drawing.Imaging;

namespace App
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            ImageViewer viewer1 = new ImageViewer(); //create an image viewer
            ImageViewer viewer2 = new ImageViewer();
            ImageViewer viewer3 = new ImageViewer();
            ImageViewer viewer4 = new ImageViewer();

            Capture capture = new Capture(); //create a camera captue
            int i = 0;
            Image<Bgr, Byte> img = new Image<Bgr, byte>("H:\\ImagineCup\\Shapes.jpg");

            Application.Idle += new EventHandler(delegate(object sender, EventArgs e)
            {  //run this until application closed (close button click on image viewer)

                img = capture.QueryFrame();
                viewer1.Image = img; //draw the image obtained from camera

                Image<Gray, Byte> gray = img.Convert<Gray, Byte>().PyrDown().PyrUp();
                //gray = gray.ThresholdBinary(new Gray(20), new Gray(180));
                gray = gray.ThresholdToZero(new Gray(80));
                Gray cannyThreshold = new Gray(100);
                Gray cannyThresholdLinking = new Gray(20);
                Gray circleAccumulatorThreshold = new Gray(120);

                Image<Gray, Byte> cannyEdges = gray.Canny(cannyThreshold, cannyThresholdLinking);
                LineSegment2D[] lines = cannyEdges.HoughLinesBinary(
                    10, //Distance resolution in pixel-related units
                    Math.PI / 45.0, //Angle resolution measured in radians.
                    20, //threshold
                    30, //min Line width
                    10 //gap between lines
                    )[0]; //Get the lines from the first channel
                Image<Bgr, Byte> newImage = img.CopyBlank();
                //cannyEdges.SmoothBlur(10, 10);
                Random random = new Random();
                using (MemStorage storage = new MemStorage()) //allocate storage for contour approximation
                    for (Contour<Point> contours = cannyEdges.FindContours(Emgu.CV.CvEnum.CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_TC89_KCOS , Emgu.CV.CvEnum.RETR_TYPE.CV_RETR_TREE); contours != null; contours = contours.HNext)
                    {
                        
                        Contour<Point> currentContour = contours.ApproxPoly(contours.Perimeter * 0.001, storage);
                        if (currentContour.Area > 1000)
                        {
                            //newImage.Draw(currentContour, new Bgr(Color.Cyan), new Bgr(Color.BlueViolet), 255, 1);
                            Int32 r = random.Next(255);
                            Int32 b = random.Next(255);
                            Int32 g = random.Next(255);
                            //newImage.Draw(currentContour, new Bgr(r, b, g), 2);
                            newImage.FillConvexPoly(currentContour.ToArray() , new Bgr(b, g, r));
                        }
                    }

                viewer2.Image = gray;
                viewer3.Image = cannyEdges;
                Bitmap bitmapImage = newImage.Bitmap;
                bitmapImage.MakeTransparent(Color.Black);
                Image<Bgr, byte> finalImage = new Image<Bgr, byte>(bitmapImage);
                finalImage = img + finalImage;
                viewer4.Image = finalImage;
                Thread.Sleep(100);
            });
            //viewer1.ShowDialog(); //show the image viewer
            Thread secondThread = new Thread(delegate()
            {
                viewer1.ShowDialog();
            });
            Thread thirdThread = new Thread(delegate()
            {
                viewer3.ShowDialog();
            });
            Thread fourthThread = new Thread(delegate()
            {
                viewer4.ShowDialog();
            });
            secondThread.Start();
            thirdThread.Start();
            fourthThread.Start();
            viewer2.ShowDialog();
            
        }
    }
}
